﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Search.Query;
using Microsoft.SharePoint.Utilities;
using System.Text.RegularExpressions;
using Kiiro.Common.Entities;
using Kiiro.Common.Utility;
using Kiiro.DataAccess;

using SearchFields = Kiiro.Common.Utility.Constants.SearchFields;
using SearchTypes = Kiiro.Common.Utility.Constants.SearchTypes;

namespace Kiiro.Model
{
    public class SearchModel
    {
        private static List<string> AllCustomTypes = new List<string> ( );

        public static Midori Search ( string keyword, string scope, Guid siteCollectionId, string serverRelativeUrl, User currUser )
        {
            Midori midori = new Midori ( );

            try
            {
                if ( keyword != null )
                {
                    AllCustomTypes = CustomModel.GetCustomContentTypeNames ( siteCollectionId, serverRelativeUrl );
                    KeywordQuery kq = null;

                    using ( SPSite site = new SPSite ( siteCollectionId ) )
                    {
                        kq = new KeywordQuery ( site );
                        kq.SiteContext = new Uri ( site.Url );
                    }

                    if ( kq != null )
                    {
                        kq.KeywordInclusion = KeywordInclusion.AllKeywords;
                        kq.ResultTypes = ResultType.RelevantResults; // WSS only supports RelevantResults
                        kq.TrimDuplicates = true;

                        foreach ( string searchField in SearchFields.AllSearchFields )
                            kq.SelectProperties.Add ( searchField );

                        foreach ( string searchType in SearchTypes.AllSearchTypes )
                            kq.QueryText += string.Format ( "ContentType:\"{0}\" ", searchType );

                        foreach ( string searchType in AllCustomTypes )
                            kq.QueryText += string.Format ( "ContentType:\"{0}\" ", searchType );

                        if ( !string.IsNullOrEmpty ( scope ) && scope.Contains ( "http" ) )
                            kq.QueryText += string.Format ( "site:\"{0}\" ", scope );

                        kq.QueryText += keyword;

                        if ( SPSecurity.AuthenticationMode != System.Web.Configuration.AuthenticationMode.Windows )
                            kq.AuthenticationType = QueryAuthenticationType.PluggableAuthenticatedQuery;
                        else
                            kq.AuthenticationType = QueryAuthenticationType.NtAuthenticatedQuery;

                        ResultTableCollection rtc = kq.Execute ( );
                        ResultTable rt = rtc [ ResultType.RelevantResults ];

                        midori = ProcessSearchResultTable ( rt, siteCollectionId, serverRelativeUrl );

                        if ( midori.AllEntities ( ).Count > 0 )
                            midori = ProcessMidoriResults ( midori, siteCollectionId, serverRelativeUrl, currUser );
                    }
                }
            }
            catch ( Exception ex )
            {
                ExceptionManagement.ExceptionManager.HandleException ( ex, true );
            }

            return midori;
        }

        /// <summary>
        /// Gets a list of fully populated comment entities using the ids from the passed comment entities
        /// </summary>
        /// <param name="comments">A list of comments that we want to populate properties for. We use these ids to populate the returned list of comments.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<Comment> GetAllComments ( List<Comment> comments, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( comments.Count > 0 )
            {
                List<int> commentIds = new List<int> ( );

                if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
                {
                    // if search was at portal level, we'll need to group the comments by server relative url and 
                    //     call the CommentModel for each server relative url and its corresponding commentIds
                    comments.Sort ( new Comparison<Comment> ( SortCommentsByServerRelativeUrl ) );

                    Dictionary<string, List<int>> commentGroups = new Dictionary<string, List<int>> ( );
                    foreach ( Comment comment in comments )
                    {
                        if ( commentGroups.ContainsKey ( serverRelativeUrl + comment.ServerRelativeUrl ) )
                            commentGroups [ comment.ServerRelativeUrl ].Add ( comment.Id );
                        else
                            commentGroups.Add ( serverRelativeUrl + comment.ServerRelativeUrl, new List<int> ( ) { comment.Id } );
                    }

                    comments.Clear ( );
                    foreach ( string key in commentGroups.Keys )
                        comments.AddRange ( CommentModel.GetCommentsByIds ( commentGroups [ key ], siteCollectionId, key ) );
                }
                else
                {
                    foreach ( Comment discussion in comments )
                        commentIds.Add ( discussion.Id );

                    if ( commentIds.Count > 0 )
                        comments = CommentModel.GetCommentsByIds ( commentIds, siteCollectionId, serverRelativeUrl );
                }
            }

            return comments;
        }

        /// <summary>
        /// Gets a list of fully populated custom item entities using the ids from the passed custom item entities
        /// </summary>
        /// <param name="customItems">A list of custom items that we want to populate properties for. We use these ids to populate the returned list of custom items.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<CustomItem> GetAllCustomItems ( List<CustomItem> customItems, Guid siteCollectionId, string serverRelativeUrl )
        {
            return CustomModel.GetAllCustomItems ( customItems, siteCollectionId, serverRelativeUrl );
        }

        /// <summary>
        /// Gets a list of fully populated discussion entities using the ids from the passed discussion entities
        /// </summary>
        /// <param name="discussions">A list of discussions that we want to populate properties for. We use these ids to populate the returned list of discussions.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<Discussion> GetAllDiscussions ( List<Discussion> discussions, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( discussions.Count > 0 )
            {
                List<int> discussionIds = new List<int> ( );

                if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
                {
                    // if search was at portal level, we'll need to group the discussions by server relative url and 
                    //     call the DiscussionModel for each server relative url and its corresponding discussionIds
                    discussions.Sort ( new Comparison<Discussion> ( SortDiscussionsByServerRelativeUrl ) );

                    Dictionary<string, List<int>> discussionGroups = new Dictionary<string, List<int>> ( );
                    foreach ( Discussion discussion in discussions )
                    {
                        if ( discussionGroups.ContainsKey ( serverRelativeUrl + discussion.ServerRelativeUrl ) )
                            discussionGroups [ serverRelativeUrl + discussion.ServerRelativeUrl ].Add ( discussion.Id );
                        else
                            discussionGroups.Add ( serverRelativeUrl + discussion.ServerRelativeUrl, new List<int> ( ) { discussion.Id } );
                    }

                    discussions.Clear ( );
                    foreach ( string key in discussionGroups.Keys )
                        discussions.AddRange ( DiscussionModel.GetDiscussionsByIds ( discussionGroups [ key ], siteCollectionId, key ) );
                }
                else
                {
                    foreach ( Discussion discussion in discussions )
                        discussionIds.Add ( discussion.Id );

                    if ( discussionIds.Count > 0 )
                        discussions = DiscussionModel.GetDiscussionsByIds ( discussionIds, siteCollectionId, serverRelativeUrl );
                }
            }

            return discussions;
        }

        /// <summary>
        /// Gets a list of fully populated document entities using the ids from the passed document entities
        /// </summary>
        /// <param name="documents">A list of documents that we want to populate properties for. We use these ids to populate the returned list of documents.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<Document> GetAllDocuments ( List<Document> documents, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( documents.Count > 0 )
            {
                if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
                {
                    // if search was at portal level, we'll need to group the documents by server relative url and 
                    //     call the DocumentModel for each server relative url and its corresponding documentIds
                    documents.Sort ( new Comparison<Document> ( SortDocumentsByServerRelativeUrl ) );

                    Dictionary<string, List<int>> documentGroupsIds = new Dictionary<string, List<int>> ( );
                    Dictionary<string, List<string>> documentGroupsUrls = new Dictionary<string, List<string>> ( );

                    // documents may or may not have ids. If document does not have id we'll have to load it by url.
                    foreach ( Document document in documents )
                    {
                        if ( document.Id != default ( int ) )
                        {
                            if ( documentGroupsIds.ContainsKey ( serverRelativeUrl + document.ServerRelativeUrl ) )
                                documentGroupsIds [ serverRelativeUrl + document.ServerRelativeUrl ].Add ( document.Id );
                            else
                                documentGroupsIds.Add ( serverRelativeUrl + document.ServerRelativeUrl, new List<int> ( ) { document.Id } );
                        }
                        else
                        {
                            if ( documentGroupsUrls.ContainsKey ( serverRelativeUrl + document.ServerRelativeUrl ) )
                                documentGroupsUrls [ serverRelativeUrl + document.ServerRelativeUrl ].Add ( document.Url );
                            else
                                documentGroupsUrls.Add ( serverRelativeUrl + document.ServerRelativeUrl, new List<string> ( ) { document.Url } );
                        }
                    }

                    documents.Clear ( );
                    foreach ( string key in documentGroupsIds.Keys )
                        documents.AddRange ( DocumentModel.GetDocumentsByIds ( documentGroupsIds [ key ], siteCollectionId, key ) );
                    foreach ( string key in documentGroupsUrls.Keys )
                        documents.AddRange ( DocumentModel.GetDocumentsByUrls ( documentGroupsUrls [ key ], siteCollectionId, key ) );
                }
                else
                {
                    List<int> documentIds = new List<int> ( );
                    List<string> documentUrls = new List<string> ( );

                    // documents may or may not have ids. If document does not have id we'll have to load it by url.
                    foreach ( Document document in documents )
                    {
                        if ( document.Id != default ( int ) )
                            documentIds.Add ( document.Id );
                        else
                            documentUrls.Add ( document.Url );
                    }

                    documents.Clear ( );
                    if ( documentIds.Count > 0 )
                        documents.AddRange ( DocumentModel.GetDocumentsByIds ( documentIds, siteCollectionId, serverRelativeUrl ) );
                    if ( documentUrls.Count > 0 )
                        documents.AddRange ( DocumentModel.GetDocumentsByUrls ( documentUrls, siteCollectionId, serverRelativeUrl ) );
                }
            }

            return documents;
        }

        /// <summary>
        /// Gets a list of fully populated project entities using the ids from the passed project entities
        /// </summary>
        /// <param name="projects">A list of project that we want to populate properties for. We use these ids to populate the returned list of project.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<Project> GetAllProjects ( List<Project> projects, Guid siteCollectionId, string serverRelativeUrl, User currUser )
        {
            if ( projects.Count > 0 )
            {
                List<int> projectIds = new List<int> ( );

                foreach ( Project project in projects )
                    projectIds.Add ( project.Id );

                // remove projects where the current user is not a member
                List<int> projectIdsForCurrUser = currUser.IsAdministrator ? projectIds : projectIds.FindAll ( x => currUser.ProjectIds.Contains ( x ) );

                if ( projectIds.Count > 0 )
                    projects = ProjectsModel.GetProjectsByIds ( projectIdsForCurrUser, siteCollectionId, serverRelativeUrl, false );
            }

            return projects;
        }

        /// <summary>
        /// Gets a list of fully populated team member entities using the ids from the passed team member entities
        /// </summary>
        /// <param name="teamMembers">A list of team members that we want to populate properties for. We use these ids to populate the returned list of team members.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<TeamMember> GetAllTeamMembers ( List<TeamMember> teamMembers, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( teamMembers.Count > 0 )
            {
                List<int> teamMemberIds = new List<int> ( );

                if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
                {
                    // if search was at portal level, we'll need to group the teamMembers by server relative url and 
                    //     call the TeamModel for each server relative url and its corresponding teamMemberIds
                    teamMembers.Sort ( new Comparison<TeamMember> ( SortTeamMembersByServerRelativeUrl ) );

                    Dictionary<string, List<int>> teamMemberGroups = new Dictionary<string, List<int>> ( );
                    foreach ( TeamMember teamMember in teamMembers )
                    {
                        if ( teamMemberGroups.ContainsKey ( serverRelativeUrl + teamMember.ServerRelativeUrl ) )
                            teamMemberGroups [ serverRelativeUrl + teamMember.ServerRelativeUrl ].Add ( teamMember.Id );
                        else
                            teamMemberGroups.Add ( serverRelativeUrl + teamMember.ServerRelativeUrl, new List<int> ( ) { teamMember.Id } );
                    }

                    teamMembers.Clear ( );
                    foreach ( string key in teamMemberGroups.Keys )
                        teamMembers.AddRange ( TeamModel.GetTeamMembersByIds ( teamMemberGroups [ key ], siteCollectionId, key ) );
                }
                else
                {
                    foreach ( TeamMember teamMember in teamMembers )
                        teamMemberIds.Add ( teamMember.Id );

                    if ( teamMemberIds.Count > 0 )
                        teamMembers = TeamModel.GetTeamMembersByIds ( teamMemberIds, siteCollectionId, serverRelativeUrl );
                }
            }

            return teamMembers;
        }

        /// <summary>
        /// Gets a list of fully populated user entities using the ids from the passed user entities
        /// </summary>
        /// <param name="users">A list of users that we want to populate properties for. We use these ids to populate the returned list of users.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<User> GetAllUsers ( List<User> users, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( users.Count > 0 )
            {
                List<int> userIds = new List<int> ( );

                foreach ( User user in users )
                    userIds.Add ( user.Id );
                if ( userIds.Count > 0 )
                    users = UserModel.GetUsersByIds ( userIds, siteCollectionId, serverRelativeUrl );
            }
            return users;
        }

        /// <summary>
        /// Gets a list of fully populated work entities using the ids from the passed work entities
        /// </summary>
        /// <param name="works">A list of work that we want to populate properties for. We use these ids to populate the returned list of work.</param>
        /// <param name="siteCollectionId">The site collection id</param>
        /// <param name="serverRelativeUrl">The server relative url of the site that the search was performed from</param>
        /// <returns></returns>
        private static List<Work> GetAllWork ( List<Work> works, Guid siteCollectionId, string serverRelativeUrl )
        {
            if ( works.Count > 0 )
            {
                List<int> workIds = new List<int> ( );

                if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
                {
                    // if search was at portal level, we'll need to group the work by server relative url and 
                    //     call the WorkModel for each server relative url and its corresponding workIds
                    works.Sort ( new Comparison<Work> ( SortWorkByServerRelativeUrl ) );

                    Dictionary<string, List<int>> workGroups = new Dictionary<string, List<int>> ( );
                    foreach ( Work work in works )
                    {
                        if ( workGroups.ContainsKey ( serverRelativeUrl + work.ServerRelativeUrl ) )
                            workGroups [ serverRelativeUrl + work.ServerRelativeUrl ].Add ( work.Id );
                        else
                            workGroups.Add ( serverRelativeUrl + work.ServerRelativeUrl, new List<int> ( ) { work.Id } );
                    }

                    works.Clear ( );
                    foreach ( string key in workGroups.Keys )
                        works.AddRange ( WorkModel.GetWorkByIds ( workGroups [ key ], siteCollectionId, key ) );
                }
                else
                {
                    foreach ( Work work in works )
                        workIds.Add ( work.Id );

                    if ( workIds.Count > 0 )
                        works = WorkModel.GetWorkByIds ( workIds, siteCollectionId, serverRelativeUrl );
                }
            }

            return works;
        }

        private static Midori ProcessSearchResultTable ( ResultTable rt, Guid siteCollectionId, string serverRelativeUrl )
        {
            Midori midori = new Midori ( );
            Dictionary<string, string> result;
            bool isPortal;

            if ( rt != null )
            {
                isPortal = SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl );

                while ( rt.Read ( ) )
                {
                    result = new Dictionary<string, string> ( );

                    for ( int i = 0; i < SearchFields.AllSearchFields.Count; i++ )
                        result.Add ( SearchFields.AllSearchFields [ i ], rt.GetString ( i ) );

                    switch ( result [ SearchFields.ContentType ] )
                    {
                        case SearchTypes.Project:
                            if ( isPortal == true )
                            {
                                Project project = new Project ( );
                                PopulateSearchEntity ( result, project, siteCollectionId );
                                if ( !midori.Projects.Exists ( x => x.Id == project.Id ) )
                                    midori.Projects.Add ( project );
                            }
                            break;
                        case SearchTypes.User:
                            if ( isPortal == true )
                            {
                                User user = new User ( );
                                PopulateSearchEntity ( result, user, siteCollectionId );
                                if ( !midori.Users.Exists ( x => x.Id == user.Id ) )
                                    midori.Users.Add ( user );
                            }
                            break;
                        case SearchTypes.TeamMember:
                            if ( isPortal == false )
                            {
                                TeamMember teamMember = new TeamMember ( );
                                PopulateSearchEntity ( result, teamMember, siteCollectionId );
                                if ( !midori.TeamMembers.Exists ( x => x.Id == teamMember.Id ) )
                                    midori.TeamMembers.Add ( teamMember );
                            }
                            break;
                        case SearchTypes.Work:
                            Work work = new Work ( );
                            PopulateSearchEntity ( result, work, siteCollectionId );
                            if ( !midori.Work.Exists ( x => x.Id == work.Id ) )
                                midori.Work.Add ( work );
                            break;
                        case SearchTypes.Document:
                            Document document = new Document ( );
                            PopulateSearchEntity ( result, document, siteCollectionId );
                            if ( !midori.Documents.Exists ( x => x.Id == document.Id ) )
                                midori.Documents.Add ( document );
                            break;
                        case SearchTypes.Discussion:
                            Discussion discussion = new Discussion ( );
                            PopulateSearchEntity ( result, discussion, siteCollectionId );
                            if ( !midori.Discussions.Exists ( x => x.Id == discussion.Id ) )
                                midori.Discussions.Add ( discussion );
                            break;
                        case SearchTypes.Comment:
                            Comment comment = new Comment ( );
                            PopulateSearchEntity ( result, comment, siteCollectionId );
                            if ( !midori.Comments.Exists ( x => x.Id == comment.Id ) )
                                midori.Comments.Add ( comment );
                            break;
                        default:
                            if ( AllCustomTypes.Contains ( result [ SearchFields.ContentType ] ) )
                            {
                                CustomItem customItem = new CustomItem ( );
                                PopulateSearchEntity ( result, customItem, siteCollectionId );
                                if ( !midori.CustomItems.Exists ( x => x.Id == customItem.Id ) )
                                    midori.CustomItems.Add ( customItem );
                            }
                            else if ( result [ SearchFields.IsDocument ] == "1" )
                            {
                                document = new Document ( );
                                PopulateSearchEntity ( result, document, siteCollectionId );
                                document.Url = result [ SearchFields.Path ];
                                document.SiteCollectionId = siteCollectionId;
                                if ( !midori.Documents.Exists ( x => x.Id == document.Id ) )
                                    midori.Documents.Add ( document );
                            }
                            break;
                    }
                }
            }

            return midori;
        }

        private static void PopulateSearchEntity ( Dictionary<string, string> result, BaseEntity searchEntity, Guid siteCollectionId )
        {
            string temp;

            if ( new Regex ( @"\d_\.\d\d\d" ).IsMatch ( result [ SearchFields.Title ] ) )
            {
                searchEntity.Id = int.Parse ( new Regex ( @"_\.\d\d\d" ).Replace ( result [ SearchFields.Title ], "" ) );
            }
            else if ( new Regex ( @".*id=", RegexOptions.IgnoreCase ).IsMatch ( result [ SearchFields.Path ] ) )
            {
                temp = new Regex ( @".*id=", RegexOptions.IgnoreCase ).Replace ( result [ SearchFields.Path ], "" );
                searchEntity.Id = int.Parse ( new Regex ( @"_\.\d\d\d" ).Replace ( temp, "" ) );
            }

            using ( SPSite site = new SPSite ( result [ SearchFields.Path ] ) )
            {
                using ( SPWeb web = site.OpenWeb ( ) )
                {
                    searchEntity.ServerRelativeUrl = web.ServerRelativeUrl == "/" ? "" : web.ServerRelativeUrl;
                    if ( AllCustomTypes.Contains ( result [ SearchFields.ContentType ] ) )
                        searchEntity.ServerRelativeUrl = result [ SearchFields.Path ].Replace ( web.Url, searchEntity.ServerRelativeUrl );
                }
            }
        }

        private static Midori ProcessMidoriResults ( Midori midori, Guid siteCollectionId, string serverRelativeUrl, User currUser )
        {
            if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
            {
                midori.Projects = GetAllProjects ( midori.Projects, siteCollectionId, serverRelativeUrl, currUser );
                midori.Users = GetAllUsers ( midori.Users, siteCollectionId, serverRelativeUrl );
            }
            else
                midori.TeamMembers = GetAllTeamMembers ( midori.TeamMembers, siteCollectionId, serverRelativeUrl );

            midori.Comments = GetAllComments ( midori.Comments, siteCollectionId, serverRelativeUrl );
            midori.CustomItems = GetAllCustomItems ( midori.CustomItems, siteCollectionId, serverRelativeUrl );
            midori.Discussions = GetAllDiscussions ( midori.Discussions, siteCollectionId, serverRelativeUrl );
            midori.Documents = GetAllDocuments ( midori.Documents, siteCollectionId, serverRelativeUrl );
            midori.Work = GetAllWork ( midori.Work, siteCollectionId, serverRelativeUrl );

            return midori;
        }

        public static List<Project> LookupProjectsNames ( Midori midori, Guid siteCollectionId, string serverRelativeUrl )
        {
            List<Project> projects = new List<Project> ( );
            List<string> projectsUrls = new List<string> ( );

            if ( SPHelpers.IsPortal ( siteCollectionId, serverRelativeUrl ) )
            {
                List<BaseEntity> allEntities = midori.AllEntities ( );
                foreach ( BaseEntity entity in allEntities )
                {
                    if ( !( entity is Project ) && !( entity is User ) )
                    {
                        string url = SPHelpers.GetServerRelativeWebUrl ( entity.SiteCollectionId, entity.ServerRelativeUrl );
                        if ( !projectsUrls.Contains ( url ) )
                            projectsUrls.Add ( url );
                    }
                }

                foreach ( string projectUrl in projectsUrls )
                {
                    Project project = ProjectsModel.GetByServerRelativeWebUrl ( siteCollectionId, projectUrl );
                    if ( project != null )
                        projects.Add ( ProjectsModel.GetByServerRelativeWebUrl ( siteCollectionId, projectUrl ) );
                }
            }

            return projects;
        }

        #region Sorts
        private static int SortBaseEntitiesByServerRelativeUrl ( BaseEntity x, BaseEntity y )
        {
            int returnValue = default ( int );

            if ( string.IsNullOrEmpty ( x.ServerRelativeUrl ) && string.IsNullOrEmpty ( y.ServerRelativeUrl )
                || ( x.ServerRelativeUrl == y.ServerRelativeUrl ) )
            {
                returnValue = 0;
            }
            else if ( string.IsNullOrEmpty ( x.ServerRelativeUrl ) && !string.IsNullOrEmpty ( y.ServerRelativeUrl ) )
            {
                returnValue = 1;
            }
            else if ( !string.IsNullOrEmpty ( x.ServerRelativeUrl ) && string.IsNullOrEmpty ( y.ServerRelativeUrl ) )
            {
                returnValue = -1;
            }
            else if ( !string.IsNullOrEmpty ( x.ServerRelativeUrl ) && !string.IsNullOrEmpty ( y.ServerRelativeUrl ) )
            {
                x.ServerRelativeUrl.CompareTo ( y.ServerRelativeUrl );
            }

            return returnValue;
        }
        private static int SortCommentsByServerRelativeUrl ( Comment x, Comment y )
        {
            return SortBaseEntitiesByServerRelativeUrl ( x, y );
        }
        private static int SortDiscussionsByServerRelativeUrl ( Discussion x, Discussion y )
        {
            return SortBaseEntitiesByServerRelativeUrl ( x, y );
        }
        private static int SortDocumentsByServerRelativeUrl ( Document x, Document y )
        {
            return SortBaseEntitiesByServerRelativeUrl ( x, y );
        }
        private static int SortTeamMembersByServerRelativeUrl ( TeamMember x, TeamMember y )
        {
            return SortBaseEntitiesByServerRelativeUrl ( x, y );
        }
        private static int SortWorkByServerRelativeUrl ( Work x, Work y )
        {
            return SortBaseEntitiesByServerRelativeUrl ( x, y );
        }
        #endregion
    }
}

/*************************************************************************
 * 
 * $Log: /Internal Projects/Kiiro/Kiiro.Model/SearchModel.cs $
 * 
 * 6     17/08/09 10:29a Camerons
 * Added check-in comments section
 * 
 ************************************************************************/